package com.echo.week;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @Author echo
 * @Description CAS 出现ABA问题案例以及解决方案
 * @Date 2023/10/17.
 * @Version 1.0
 */
public class DemoCAS {

    static AtomicInteger ar= new AtomicInteger(100);

    static AtomicStampedReference<Integer> asr = new AtomicStampedReference<>(100,1);

    public static void main(String[] args) throws InterruptedException {
        System.out.println("=======ABA问题的产生=======");
        Thread t1 = new Thread(()->{
            ar.compareAndSet(100,101);
            ar.compareAndSet(101,100);
        },"t1");
        t1.start();

        Thread t2 = new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(ar.compareAndSet(100,2022)+"\t"+ar.get());
        },"t2");
        t2.start();

        //顺序执行，AtomicInteger案列先执行
        t1.join();
        t2.join();

        System.out.println("=======ABA问题的解决=======");
        new Thread(()->{
            int stamp = asr.getStamp();
            System.out.println(Thread.currentThread().getName()+"第一次版本号："+stamp);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            asr.compareAndSet(100,101,asr.getStamp(), asr.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"第二次版本号："+asr.getStamp()+","+asr.getReference());

            asr.compareAndSet(101,100,asr.getStamp(), asr.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"第三次版本号："+asr.getStamp()+","+asr.getReference());
        },"t3").start();


        new Thread(()->{
            int stamp = asr.getStamp();
            System.out.println(Thread.currentThread().getName()+"第一次版本号："+stamp);
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            boolean result = asr.compareAndSet(100, 2022, stamp, stamp + 1);
            System.out.println(Thread.currentThread().getName()+"修改成功与否："+result+"当前版本号："+asr.getStamp());

            System.out.println(Thread.currentThread().getName()+"当前实际值："+asr.getReference());
        },"t4").start();



    }
}
